package com.ziytek.web.citizen.controller;

import com.google.gson.Gson;
import com.ziytek.web.citizen.constant.ApiConstant;
import com.ziytek.web.citizen.constant.NumConstant;
import com.ziytek.web.citizen.constant.ServerConstant;
import com.ziytek.web.citizen.event.PushEvent;
import com.ziytek.web.citizen.exception.IssuedException;
import com.ziytek.web.citizen.model.bean.IssuedResults;
import com.ziytek.web.citizen.model.req.StepSettingsIssuedReq;
import com.ziytek.web.citizen.model.req.StepSettingsIssuedSingleReq;
import com.ziytek.web.citizen.model.rsp.StepSettingsIssuedRsp;
import com.ziytek.web.citizen.model.rsp.StepSettingsIssuedSingleRsp;
import com.ziytek.web.citizen.service.BatchNoService;
import com.ziytek.web.citizen.service.itf.OfflineService;
import com.ziytek.web.citizen.service.itf.StepSettingsIssuedSingleService;
import com.ziytek.web.citizen.util.UuidUtil;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * 指令下发接口
 *
 * @author fenghx
 * @version 1.0
 * @className SettingController
 * Description:设置接口
 * @date 2023/12/7 16:46
 **/
@Slf4j
@RestController
@RequestMapping(ApiConstant.API_CABINET)
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class StepIssuedController {
    private final Gson gson;
    private final ApplicationContext context;
    private final OfflineService offlineService;
    private final BatchNoService batchNoService;
    private final StepSettingsIssuedSingleService stepSettingsIssuedSingleService;


    /**
     * 执行工步指令下发接口
     *
     * @param request 请求参数
     * @return 执行工步指令下发响应
     */
    @PostMapping(ApiConstant.STEP_ISSUED)
    public StepSettingsIssuedRsp stepIssued(@Valid @RequestBody StepSettingsIssuedReq request) {
        var requestId = UuidUtil.getUuid();
        log.info("整体指令下发请求Issuance and execution of the step setting plan for the partition cabinet:{}，requestId:{}", gson.toJson(request), requestId);

        var start = System.currentTimeMillis();
        var response = new StepSettingsIssuedRsp();
        response.error("指令执行失败");

        // 终止指令执行
        var responseInterrupt = getInterruptStepSettingsIssuedRsp(request, response);
        if (null != responseInterrupt) {
            return responseInterrupt;
        }

        boolean allSuccess = true;
        List<IssuedResults> issuedResults = new ArrayList<>();
        for (var cabinetNo : request.getCabinetNoList()) {
            var issuedResult = new IssuedResults();
            issuedResult.setCabinetNo(cabinetNo);
            issuedResult.setResult(true);

            // 设备是否在线
            if (!offlineService.online(Integer.parseInt(cabinetNo))) {
                allSuccess = false;
                response.error("设备不在线");
                issuedResult.setResult(false);
                issuedResults.add(issuedResult);
                log.info("整体指令下发失败,设备不在线single channel stepIssued success,requestId:{},response:{}", requestId, gson.toJson(response));
                continue;
            }

            // 新增批次数据
            batchNoService.insertBatchNo(Integer.parseInt(cabinetNo));

            var singleRequest = new StepSettingsIssuedSingleReq();
            singleRequest.setBoardNo(NumConstant.INT_TWO_FIFTY_FIVE);
            singleRequest.setChannelNo(NumConstant.INT_TWO_FIFTY_FIVE);
            singleRequest.setId(request.getId());
            singleRequest.setCabinetNo(cabinetNo);
            singleRequest.setToken(request.getToken());

            try {
                log.info("整体指令下发请求stepIssued channel stepIssued success,cabinetNo:{}", cabinetNo);
                stepSettingsIssuedSingleService.issued(singleRequest);
            } catch (IssuedException e) {
                log.info("整体指令下发请求single channel stepIssued error,cabinetNo:{},error:{}", cabinetNo, e.getMessage());
                issuedResult.setResult(false);
            }
            issuedResults.add(issuedResult);

            // 先推送首界面的实时数据
            context.publishEvent(new PushEvent(String.valueOf(Integer.parseInt(cabinetNo))));
        }

        var end = System.currentTimeMillis();
        response.setData(issuedResults);
        if (allSuccess) {
            response.success();
        }

        log.info("整体指令下发成功执行耗时:{}ms success,requestId:{},response:{}", end - start, requestId, gson.toJson(response));
        return response;
    }

    private StepSettingsIssuedRsp getInterruptStepSettingsIssuedRsp(StepSettingsIssuedReq request, StepSettingsIssuedRsp response) {
        if (Integer.parseInt(ServerConstant.INTERRUPT_ID) != request.getId()) {
            return null;
        }

        var requestId = UuidUtil.getUuid();
        List<IssuedResults> issuedResults = new ArrayList<>();
        var cabinetNo = request.getCabinetNoList().getFirst();
        var issuedResult = new IssuedResults();
        issuedResult.setCabinetNo(cabinetNo);
        issuedResult.setResult(true);

        // 设备是否在线
        if (!offlineService.online(Integer.parseInt(cabinetNo))) {
            response.error("设备不在线");
            issuedResult.setResult(false);
            issuedResults.add(issuedResult);
            response.setData(issuedResults);
            log.info("整体终止指令下发失败,设备不在线single channel stepIssued success,requestId:{},response:{}", requestId, gson.toJson(response));
            return response;
        }

        try {
            var singleRequest = new StepSettingsIssuedSingleReq();
            singleRequest.setId(request.getId());
            singleRequest.setCabinetNo(cabinetNo);
            singleRequest.setToken(request.getToken());
            singleRequest.setBoardNo(NumConstant.INT_TWO_FIFTY_FIVE);
            singleRequest.setChannelNo(NumConstant.INT_TWO_FIFTY_FIVE);
            stepSettingsIssuedSingleService.endIssued(singleRequest);
        } catch (IssuedException e) {
            log.info("整体终止指令下发请求interrupt channel stepIssued error,cabinetNo:{},error:{}", cabinetNo, e.getMessage());
            issuedResult.setResult(false);
        }
        issuedResults.add(issuedResult);
        response.setData(issuedResults);
        response.success();

        // 先推送首界面的实时数据
        context.publishEvent(new PushEvent(String.valueOf(Integer.parseInt(cabinetNo))));
        return response;
    }


    /**
     * 单个通道执行工步指令下发接口
     *
     * @param request 请求参数
     * @return 单个通道执行工步指令下发响应
     */
    @PostMapping(ApiConstant.STEP_ISSUED_SINGLE)
    public StepSettingsIssuedSingleRsp stepIssuedSingle(@Valid @RequestBody StepSettingsIssuedSingleReq request) {
        var requestId = UuidUtil.getUuid();
        log.info("单通道指令下发请求single channel Issuance and execution of the step setting plan for the partition cabinet:{}，requestId:{}", gson.toJson(request), requestId);

        var response = new StepSettingsIssuedSingleRsp();
        response.error("指令执行失败");
        // 设备是否在线
        if (!offlineService.online(Integer.parseInt(request.getCabinetNo()))) {
            response.error("设备不在线");
            log.info("单通道指令下发失败,设备不在线single channel stepIssued success,requestId:{},response:{}", requestId, gson.toJson(response));
            return response;
        }

        try {
            // 终止指令执行
            // 第一行实际对应设备的00地址
            if (null != request.getBoardNo()) {
                request.setBoardNo(request.getBoardNo() - NumConstant.INT_ONE);
            }
            if (Integer.parseInt(ServerConstant.INTERRUPT_ID) == request.getId()) {
                stepSettingsIssuedSingleService.endIssued(request);
                response.success();

                // 先推送首界面的实时数据
                context.publishEvent(new PushEvent(String.valueOf(Integer.parseInt(request.getCabinetNo()))));

                log.info("单通道终止指令下发single interrupt channel stepIssued success,requestId:{},response:{}", requestId, gson.toJson(response));
                return response;
            }

            // 正常指令执行
            stepSettingsIssuedSingleService.issued(request);
        } catch (IssuedException e) {
            response.error(e.getMessage());
            log.info("单通道指令下发请求single channel stepIssued error,requestId:{},error:{}", requestId, e.getMessage());
            return response;
        }

        response.success();

        // 先推送首界面的实时数据
        context.publishEvent(new PushEvent(String.valueOf(Integer.parseInt(request.getCabinetNo()))));

        log.info("单通道指令下发成功single channel stepIssued success,requestId:{},response:{}", requestId, gson.toJson(response));
        return response;
    }
}
